grammar Lispy;

@header {
  import java.util.HashMap;
  import java.util.Vector;
}

@members {
  HashMap<String, Expr> syms = new HashMap<String, Expr>();
}

prog
  : (expr {
    int i = $expr.code.run();
    System.out.println(">>" + i);
  })+ EOF
  ;
  
expr returns [Expr code]
  : NUM {
      $code = new NumExpr(syms, $NUM.text);
    }
  | ID {
    $code = new SymExpr(syms, $ID.text);
  }
  | '('
    {Vector args = new Vector();}
    fun {Fun f = $fun.f;}
    (e=expr {args.add($e.code);})* 
    ')'
    {
      try {
        $code = new FunExpr(syms, f, args);
      } catch(Exception exception) {
        System.err.println("ERROR: " + exception);
        exception.printStackTrace();
        $code = null;
      }
    }
  ;

fun returns [Fun f]
  : 'read'    {$f = new ReadFun(syms);}
  | 'print'   {$f = new PrintFun(syms);}
  | 'let' ID  {$f = new LetFun(syms, $ID.text);}
  | 'repeat' ID {$f = new ForLoopFun(syms, $ID.text);}
  ;

NUM : ('0' .. '9')+;
WS : (' ' | '\t' | '\n') {skip();};
ID : ('a' .. 'z');

